﻿using CTP.CRM.Core.PublicMethords;
using CTP.CRM.Core.Redis;
using CTP.CRM.Repository;
using CTP.CRM.Repository.Demo.Entitys;
using CTP.CRM.Repository.Demo.ValueObjects;

namespace CTP.CRM.Repository.Demo.Services
{
    public class DemoRepository : BasicRepository<DemoEntity>, IDemoRepository, IScopedDependency
    {
        /*
            一般情况下常规的增删改方法不需要自己实现，只需要按照 BasicRepository 中的格式原封不动的暴露出去即可，
            比如这里接口 只声明了 UpdateAsync 和 InsertReturnIdentityAsync 接口的定义，但是这两个方法的实现我们不用写，直接交给父类实现即可
        */

        #region 根据主键获取单条数据

        /// <summary>
        /// 根据主键获取单条数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<DemoEntity> MyGetByIdAsync(int id)
        {
            /*

            //以下两种方法都不会因为没找到数据而抛异常
            var model1 = base.GetFirst(m => m.Id == 0);
            var model = base.GetSingle(m => m.Id == 0);

            //同样的写法在linq下，如果不加 OrDefault 一定会报错
            var model = base.GetList().Single(m => m.Id == 0);
            var model1 = base.GetList().First(m => m.Id == 0);

            */
            return base.GetSingleAsync(it => it.Id == id);
        }

        #endregion 根据主键获取单条数据

        #region 分页获取

        /// <summary>
        /// 分页获取
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<UnifyPageResultDto<DemoEntity>> GetListByPage(int pageSize, int pageindex, string name)
        {
            var list = await AsQueryable()
                .WhereIF(!string.IsNullOrEmpty(name), a => a.Name.Contains(name))
                .ToPagedListAsync(pageindex, pageSize);

            return list;
        }

        #endregion 分页获取

        #region 参数为实体

        /// <summary>
        /// 参数很多的时候，定义模型接受参数
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public async Task<List<DemoEntity>> InputToValueObject(DemoValueObject obj)
        {
            var list = await AsQueryable().ToListAsync();
            return list;
        }

        #endregion 参数为实体

        #region 执行原生sql语句

        /// <summary>
        /// 执行原生sql语句
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public async Task<UnifyPageResultDto<DemoValueObject>> OriginalSql(DemoValueObject obj)
        {
            var parameters = new List<SugarParameter>();
            var sql = @$"
                select
                    a.id,
                    a.Name,
                    a.Age,
                    a.Description
                from t_demo a
                where 1=1
                    {" and a.Name like @Name ".WhereIF(!string.IsNullOrEmpty(obj.Name), obj.Name, ref parameters)}
                order by a.id desc ";

            var list = await Context.SqlQueryable<DemoValueObject>(sql)
                .AddParameters(parameters)
                .ToPagedListAsync(obj.PageIndex, obj.PageSize);

            return list;
        }

        #endregion 执行原生sql语句

        #region 简单事务

        public async Task Transaction()
        {
            using (var ts = TransactionScopeHelper.Create())
            {
                await base.InsertAsync(new DemoEntity { Name = "1111" });
                await base.InsertAsync(new DemoEntity { Name = "222" });
                await base.InsertAsync(new DemoEntity { Name = "3333" });

                //throw new BusinessException("E05632","手动抛异常");
                await base.InsertAsync(new DemoEntity { Name = "4444" });

                ts.Complete();
            }
        }

        #endregion 简单事务

        #region 夸方法事务

        public async Task MultipleMethodTrans1()
        {
            await base.InsertAsync(new DemoEntity { Name = "---" });
            await base.InsertAsync(new DemoEntity { Name = "+++" });
        }

        public async Task MultipleMethodTrans2()
        {
            //throw new BusinessException(message: "手动抛出异常");
            await base.InsertAsync(new DemoEntity { Name = "xxx" });
        }

        #endregion 夸方法事务

        #region 事务嵌套

        public async Task InternalTrans()
        {
            using (var ts = TransactionScopeHelper.Create())
            {
                await Transaction();
                await MultipleMethodTrans1();
                //throw new BusinessException(message: "手动抛出异常");
                await base.InsertAsync(new DemoEntity { Name = "xxx" });

                ts.Complete();
            }
        }

        #endregion 事务嵌套

        #region 局部更新

        public async Task UpdatePartColumns(DemoEntity entity)
        {
            Context.Updateable(entity).UpdateColumns(m => new { m.Description, m.Name }).ExecuteCommand();
            // UPDATE `test`  SET `Name`= 'string',`Description`= 'string'  WHERE `id`= 5

            Context.Updateable(entity).IgnoreColumns(m => new { m.CreateUserId, m.Age }).ExecuteCommand();
            // UPDATE `test`  SET`IsDeleted`= 0,`Name`= 'string',`Description`= 'string',`EnabledMark`= 0,`DeleteUserId`= 0,`DeleteTime`= '2022/8/13 23:42:36',`CreateTime`= '2015/5/12 0:00:00',`UpdateUserId`= 0,`UpdateTime`= '2022/8/13 23:55:27'  WHERE `id`= 5
        }

        #endregion 局部更新

        #region 导航属性

        /// <summary>
        /// 导航属性
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<bool> EntityRelationSave(DemoEntity entity)
        {
            var res = await Context.InsertNav(entity).Include(m => m.DemoDetailList).ExecuteCommandAsync();
            return res;
        }

        #endregion 导航属性

        #region 缓存

        /// <summary>
        /// 获取数据包含缓存
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<DemoEntity> GetDataCache(int id)
        {
            var redisKey = $"Demo:Endity:{id}";
            var demo = await RedisHelper.Client.GetAsync<DemoEntity>(redisKey);
            if (demo != null)
                return demo;

            var aa = Context.Ado.Connection;
            demo = await base.GetSingleAsync(m => m.Id == id);

            await RedisHelper.Client.SetAsync(redisKey, demo, 60 * 20);

            return demo;
        }

        #endregion 缓存
    }
}